#pragma warning( disable: 4995 4996 )

#include <windows.h>
#include <strsafe.h>
#include <assert.h>

#include "BasicDataTypes.h"
#include "Collections.h"
#include "DirectoriesAndFiles.h"
#include "Forms.h"

#include "commctrl.h"
#include "Program.h"

double Test_001::Program::a;
double Test_001::Program::b;
double Test_001::Program::c;
int Test_001::Program::testCases;
double Test_001::Program::A;
double Test_001::Program::B;
double Test_001::Program::C;

// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 0785D71459767238A035BDC4548BBB005DAE4476
int Test_001::Program::TestVars()
{
	double aa = a;
	double bb = b;
	double cc = c;
	double dd = A;
	int itest = testCases;
	List<string> tests ; 
	tests.Add("test1");
	tests.Add("test2");
	tests.Add("test3");
	List<string> tests2 = tests; 
	{
		string s;
		tests2.start_iteration();
		while( tests2.get_next( s ) )
		{
			Console::WriteLine( string(s) );   
		}
	}

	List<string> test3(tests);
	List<string> tests4 = test3;
	{
		string s;
		tests4.start_iteration();
		while( tests4.get_next( s ) )
		{
			Console::WriteLine( string(s) );
		}
	}

	double d123 = 1.23;
	int i123 = 123;
	string temp1 = string("We have " )+ d123 + " and " + i123;
	Console::WriteLine( string(temp1) );
	Double D123 = 1.23;
	Int32 I123 = 123;
	string temp2 = string("We have " )+ D123 + " and " + I123;
	if ( temp1 == temp2 )
		Console::WriteLine("Int32/int & Double/double to string passed");
	else
		Console::WriteLine("Int32/int & Double/double to string FAILED!");
	int failures = 0;
	if (D123 != d123)
		failures++;
	if (I123 != i123)
		failures++;
	if (temp1 != temp2)
		failures++;
	assert( failures == 0 );
	return failures;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 6383C761DEB8896EA685B8A06F0D95572285C13D
int Test_001::Program::TestStringFormat()
{
	Console::WriteLine(string(1)+" "+ 2 +" "+1 );
	string s =string(1)+" "+ 2+" "+1;
	Console::WriteLine( string(s) );
	Console::WriteLine("Why would you do this?" );
	Console::WriteLine(string("And the current day is ")+DateTime::Now().Day()+" "+DateTime::Now().Day()+" "+DateTime::Now().Day() );
	return 0;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: E7E67AC4A500C9F6D09D3D0F238A9E47678E7943
int Test_001::Program::TestArrays()
{
	List<string> tests ; 
	tests.Add("test1");
	tests.Add("test2");
	tests.Add("test3");
	{
		string s;
		tests.start_iteration();
		while( tests.get_next( s ) )
			Console::Write(string(s )+ " ");
	}

	Console::WriteLine();
	return 0;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 95150D543E30228B2B368BC0CC20C112B43677DA
int Test_001::Program::TestLists()
{
	List<string> tests;
	tests.Add("test1");
	tests.Add("test2");
	tests.Add("test3");
	{
		string s;
		tests.start_iteration();
		while( tests.get_next( s ) )
			Console::Write(string(s )+ " ");
	}

	Console::WriteLine();
	for (int i = 0; i < tests.Count(); i++)
	{
		Console::Write(string(tests[i] )+ " ");
	}
	Console::WriteLine();
	for (int k = 0; k < tests.Count(); k++)
		Console::Write(string(tests[k] )+ " ");
	Console::WriteLine();
	List<string> ss(tests);
	{
		string sss;
		ss.start_iteration();
		while( ss.get_next( sss ) )
			Console::Write(string(sss)+" " );
	}

	Console::WriteLine();
	return 0;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 72A7B7BBAB995111C9C6E753AE0374ED172CE8A7
int Test_001::Program::TestHashing()
{
	Dictionary<string,Double> grades;
	grades["Tom"] = 3.7;
	grades["Melissa"] = 3.8;
	grades["Jason"] = 2.9;
	Console::WriteLine("Grades are:");
	{
		string dKey;
		Double dValue;
		grades.start_iteration();
		while( grades.get_next( dKey, dValue ) )
		{
			Console::WriteLine(string(dKey )+ " has a GPA of " + dValue);
		}
	}

	{
		string d2Key;
		Double d2Value;
		grades.start_iteration();
		while( grades.get_next( d2Key, d2Value ) )
		{
			Console::WriteLine(string(d2Key )+ " has a GPA of " + d2Value);
		}
	}

	int failures = 0;
	if (grades["Tom"] != 3.7)
		failures++;
	if (grades["Melissa"] != 3.8)
		failures++;
	if (grades["Jason"] != 2.9)
		failures++;
	assert( failures == 0 );
	return failures;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 9A306FAC6DF51FD608C9EB730C3671803A838742
int Test_001::Program::TestDirectory()
{
	DirectoryInfo di("c:\\");
	Console::WriteLine("--- files:");
	{
		List<FileInfo> *diGetFilesCollection = di.GetFiles("d*");
		FileInfo fi;
		diGetFilesCollection->start_iteration();
		while( diGetFilesCollection->get_next( fi ) )
		{
			Console::WriteLine( string(fi.Name()) );
		}
	}

	Console::WriteLine("--- directories:");
	{
		List<DirectoryInfo> *diGetDirectoriesCollection = di.GetDirectories("p*");
		DirectoryInfo sub;
		diGetDirectoriesCollection->start_iteration();
		while( diGetDirectoriesCollection->get_next( sub ) )
		{
			Console::WriteLine( string(sub.Name()) );
		}
	}

	return 0;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 7AE5ACAB2C33570E6FA064BD81384CAB05CA28CF
int Test_001::Program::TestFiles()
{
	if ( File::Exists("c:\\this-file-should-not-exist.txt"))
		Console::WriteLine("FOUND NON-EXISTENT FILE?");
	string testFile = "c:\\test.txt";
	//File.WriteAllLines(testFile,  { "line1", "line2" });
	File::WriteAllText(testFile, "This\r\nis a long\r\nstory\r\nthe end");
	string s = File::ReadAllText(testFile);
	List<string> s2 = File::ReadAllLines( testFile ); 
	File::Delete(testFile);
	return 0;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: A8EA0FAE57F30075CCDB87B0FF4F7542F0800A06
int Test_001::Program::TestDates()
{
	DateTime d = DateTime::Now();
	Thread::Sleep(1000);
	TimeSpan ts ( DateTime::Now() , d);
	Console::WriteLine(string(ts.TotalMilliseconds())+"ms elapsed" );
	return 0;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 8968E2EE13FEE333806A52E191ED70FBF5E241A8
int Test_001::Program::TestStrings()
{
	int failures = 0;
	string s = string("test ")+1+" and "+ 2;
	List<string> s2 = s.Split( ' ' ); 
	{
		string s3;
		s2.start_iteration();
		while( s2.get_next( s3 ) )
			Console::WriteLine( string(s3) );
	}

	string s4 = "This ";
	s4 += "is ";
	s4 += "too ";
	s4 += "Cool!";
	Console::WriteLine( string(s4) );
	if (s4 == "This is too Cool!")
		Console::WriteLine("s4 passed!");
	else
	{
		Console::WriteLine("s4 failed!");
		failures++;
	}
	StringBuilder sb("This ");
	sb.Append( "is " );
	sb.Append( "too " );
	sb.Append( "Cool!" );
	Console::WriteLine( string(sb.ToString()) );
	string s5 = sb.ToString();
	if (s5 != "This is too Cool!")
	{
		Console::WriteLine("StringBuilder failed!");
		failures++;
	}
	else
		Console::WriteLine("StringBuilder passed!");
	assert( s4 == "This is too Cool!" );
	assert((s5 == "This is too Cool!") &&  "Did not get the expected value for s5" );
	return failures;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 02FC47AE2CF39273D441BA40855D9D5A0BF29DD9
int Test_001::Program::TestFactorial( int i )
{
	DateTime start = DateTime::Now();
	double factorial = 1;
	int factor = 1;
	while (factor < i)
		factorial *= factor++;
	TimeSpan ts ( DateTime::Now() , start);
	Console::WriteLine( string("Completed factorial of " )+ i + " in " + ts.TotalMilliseconds() + ": " + factorial);
	return 0;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: 00E45CE9646072BB68F65923E91144927E34CA9C
int Test_001::Program::TestUnsupportedFeatures()
{
	int failures = 0;
	//try
	{
	}
		
// BUGBUG - GoNative not currently support try catch, try rewriting
#pragma message( "GONATIVE -- removed 'catch'") 
	if ( 0 ) // was: catch (Exception)
	{
		Console::WriteLine("C# catch's aren't handled");
		failures++;
	}
	//finally
	{
		Console::WriteLine("finally in the finally");
	}
// BUGBUG - use generics/List<> instead of ArrayList() to work with GoNative
//	ArrayList al;
	Console::WriteLine("ArrayList() isn't supported - rewrite your C# to use generics (i.e. List<string>, List<myobject>, etc...)");
	return failures;
}


int Test_001::Program::TestSourceCodeSubstitution()
// this code was substituted from ..\..\test-001-native\test-001-native\substitution.cpp
// GoNative Replacement Hash: 7EA84D1225B57CC6177E0D450A48B7382234FA8F
{
	printf( "PASSED!  This is the C++ substitution code (not generated by GoNative)\n" );
	return 0;   // 0 failures!
}



// BUGBUG - need to capture comments here
// GoNative Replacement Hash: A7C0A61C55F91F487075BAF48DE32C728A25229B
int Test_001::Program::TestEnums()
{
	int failures = 0;
	Answers tom = Answers::Yes;
	if (tom != Answers::Yes)
		failures++;
#if 0
	List<Answers> everyone ; 
	everyone.Add(Answers::Maybe());
	everyone.Add(Answers::No());
	everyone.Add(Answers::Maybe());
	everyone.Add(Answers::Yes);
	if (everyone[0] != Answers::Maybe())
		failures++;
	if (everyone[1] != Answers::No())
		failures++;
	if (everyone[2] != Answers::Maybe())
		failures++;
	if (everyone[3] != Answers::Yes)
		failures++;
#endif
	return failures;
}


// BUGBUG - need to capture comments here
// GoNative Replacement Hash: E598A40552DE7F0CCDD56820C59D2403068CB774
void Test_001::Program::Main( List<string> args ) 
{
	List<string> args2;
	args2.Add("hey");
	Console::WriteLine( "Hello!" );
#if 1
	// this comment is in an 'active' code section
#endif
#if 0
	// this comment is in an 'in-active' code section
#endif
	int failures = 0;
	failures += TestVars();
	failures += TestStringFormat();
	failures += TestArrays();
	failures += TestLists();
	failures += TestHashing();
	failures += TestDirectory();
	failures += TestFiles();
	failures += TestFactorial(10);
	failures += TestFactorial(10000000);
	failures += TestFactorial(20000000);
	//failures += TestFactorial(50000000);
	//failures += TestFactorial(100000000);
	failures += TestDates();
	failures += TestStrings();
	failures += TestUnsupportedFeatures();
	failures += TestSourceCodeSubstitution();
	failures += TestEnums();
	
	Console::WriteLine(string("\nThere are a total of ")+failures+" failures\n(1 expected in C# build, 0 expected in C++ builds\n" );
	Console::WriteLine("press the enter key");
	Console::ReadLine();
	Console::WriteLine("Goodbye!");
}




int main(int argc, WCHAR* argv[] )
{
	List<string> args;
	// start from '1', .NET skips argv[0]
	for( int i = 1; i < argc; i++ )
		args.Add( argv[i] );
	Test_001::Program::Main( args );
	return 0;
}


